<template>
  <div class="operation-log">
    <el-page-header title="日志管理">
      <template #content>
        <span class="page-header-content">操作日志</span>
      </template>
    </el-page-header>

    <div class="log-content">
      <!-- 搜索栏 -->
      <el-card class="search-card">
        <el-form :model="searchForm" ref="searchFormRef" inline>
          <el-form-item label="操作人" prop="username">
            <el-input
              v-model="searchForm.username"
              placeholder="请输入操作人"
              clearable
            />
          </el-form-item>
          <el-form-item label="操作类型" prop="operType">
            <el-select
              v-model="searchForm.operType"
              placeholder="请选择操作类型"
              clearable
              style="width: 160px"
            >
              <el-option label="新增" value="新增" />
              <el-option label="修改" value="修改" />
              <el-option label="删除" value="删除" />
              <el-option label="查询" value="查询" />
              <el-option label="导出" value="导出" />
              <el-option label="审批" value="审批" />
            </el-select>
          </el-form-item>
          <el-form-item label="操作模块" prop="module">
            <el-select
              v-model="searchForm.module"
              placeholder="请选择操作模块"
              clearable
              style="width: 160px"
            >
              <el-option label="客户管理" value="客户管理" />
              <el-option label="贷款管理" value="贷款管理" />
              <el-option label="产品管理" value="产品管理" />
              <el-option label="系统管理" value="系统管理" />
              <el-option label="用户管理" value="用户管理" />
            </el-select>
          </el-form-item>
          <el-form-item label="操作状态" prop="status">
            <el-select
              v-model="searchForm.status"
              placeholder="请选择操作状态"
              clearable
              style="width: 160px"
            >
              <el-option label="成功" value="0" />
              <el-option label="失败" value="1" />
            </el-select>
          </el-form-item>
          <el-form-item label="操作时间" prop="timeRange">
            <el-date-picker
              v-model="searchForm.timeRange"
              type="datetimerange"
              range-separator="至"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              value-format="YYYY-MM-DD HH:mm:ss"
              :shortcuts="dateShortcuts"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button @click="handleReset">重置</el-button>
            <el-button type="success" @click="handleExport">导出日志</el-button>
            <el-button type="danger" @click="handleCleanLog">清空日志</el-button>
          </el-form-item>
        </el-form>
      </el-card>

      <!-- 日志表格 -->
      <el-card class="table-card">
        <div class="table-header">
          <div class="left">
            <el-button 
              type="danger" 
              :disabled="selectedIds.length === 0" 
              @click="handleDeleteSelected"
            >
              批量删除
            </el-button>
          </div>
        </div>
        <el-table
          :data="tableData"
          style="width: 100%"
          v-loading="loading"
          border
          stripe
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column type="index" label="序号" width="60" align="center" />
          <el-table-column prop="username" label="操作人" width="120">
            <template #default="scope">
              <el-tooltip
                :content="scope.row.operatorInfo || scope.row.username"
                placement="top"
                effect="light"
              >
                <span>{{ scope.row.username }}</span>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="operType" label="操作类型" width="100">
            <template #default="scope">
              <el-tag
                :type="getOperationTypeTag(scope.row.operType)"
              >
                {{ scope.row.operType }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="module" label="操作模块" width="120" />
          <el-table-column prop="title" label="操作描述" min-width="200" show-overflow-tooltip />
          <el-table-column prop="operIp" label="IP地址" width="140" />
          <el-table-column prop="status" label="状态" width="100">
            <template #default="scope">
              <el-tag
                :type="scope.row.status === 0 ? 'success' : 'danger'"
              >
                {{ scope.row.status === 0 ? '成功' : '失败' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="costTime" label="耗时" width="100">
            <template #default="scope">
              {{ scope.row.costTime }}ms
            </template>
          </el-table-column>
          <el-table-column prop="operTime" label="操作时间" width="180" />
          <el-table-column label="操作" width="120" fixed="right">
            <template #default="scope">
              <el-button
                link
                type="primary"
                @click="handleViewDetail(scope.row)"
              >
                详情
              </el-button>
              <el-button
                link
                type="danger"
                @click="handleDelete(scope.row)"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <div class="pagination">
          <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 50, 100]"
            :total="total"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </div>
      </el-card>

      <!-- 详情弹窗 -->
      <el-dialog
        v-model="detailVisible"
        title="操作日志详情"
        width="800px"
        destroy-on-close
      >
        <el-descriptions :column="2" border>
          <el-descriptions-item label="操作人">
            {{ currentLog.username }}
          </el-descriptions-item>
          <el-descriptions-item label="操作类型">
            <el-tag :type="getOperationTypeTag(currentLog.operType)">
              {{ currentLog.operType }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="操作模块">
            {{ currentLog.module }}
          </el-descriptions-item>
          <el-descriptions-item label="IP地址">
            {{ currentLog.operIp }}
          </el-descriptions-item>
          <el-descriptions-item label="操作状态">
            <el-tag :type="currentLog.status === 0 ? 'success' : 'danger'">
              {{ currentLog.status === 0 ? '成功' : '失败' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="操作时间">
            {{ currentLog.operTime }}
          </el-descriptions-item>
          <el-descriptions-item label="操作描述" :span="2">
            {{ currentLog.title }}
          </el-descriptions-item>
          <el-descriptions-item label="请求方法" :span="2">
            {{ currentLog.method }}
          </el-descriptions-item>
          <el-descriptions-item label="请求参数" :span="2">
            <pre class="code-block">{{ formatJson(currentLog.operParam) }}</pre>
          </el-descriptions-item>
          <el-descriptions-item label="响应结果" :span="2">
            <pre class="code-block">{{ formatJson(currentLog.jsonResult) }}</pre>
          </el-descriptions-item>
          <el-descriptions-item v-if="currentLog.status === 1" label="错误信息" :span="2">
            <pre class="code-block error">{{ currentLog.errorMsg }}</pre>
          </el-descriptions-item>
        </el-descriptions>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { operLogApi } from '@/api/monitor'

export default {
  name: 'OperationLog',
  setup() {
    // 搜索表单
    const searchForm = reactive({
      username: '',
      operType: '',
      module: '',
      status: '',
      timeRange: [],
      pageNum: 1,
      pageSize: 10
    })

    // 日期快捷选项
    const dateShortcuts = [
      {
        text: '最近一小时',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000)
          return [start, end]
        }
      },
      {
        text: '今天',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setHours(0, 0, 0, 0)
          return [start, end]
        }
      },
      {
        text: '最近三天',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
          return [start, end]
        }
      },
      {
        text: '最近一周',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
          return [start, end]
        }
      }
    ]

    // 表格数据
    const loading = ref(false)
    const currentPage = ref(1)
    const pageSize = ref(10)
    const total = ref(0)
    const tableData = ref([])
    const selectedIds = ref([])

    // 详情弹窗
    const detailVisible = ref(false)
    const currentLog = ref({})

    // 操作类型标签
    const getOperationTypeTag = (type) => {
      if (type === '新增') return 'success'
      if (type === '修改') return 'warning'
      if (type === '删除') return 'danger'
      if (type === '查询') return 'info'
      if (type === '导出') return ''
      if (type === '审批') return 'primary'
      return 'info'
    }

    // 格式化JSON
    const formatJson = (json) => {
      if (!json) return ''
      try {
        if (typeof json === 'string') {
          return JSON.stringify(JSON.parse(json), null, 2)
        }
        return JSON.stringify(json, null, 2)
      } catch (e) {
        return json
      }
    }

    // 获取操作日志列表
    const getOperLogList = () => {
      loading.value = true
      // 处理时间范围
      const params = { ...searchForm }
      if (params.timeRange && params.timeRange.length === 2) {
        params.startTime = params.timeRange[0]
        params.endTime = params.timeRange[1]
      }
      delete params.timeRange

      operLogApi.getList(params).then(res => {
        if (res.code === 200) {
          tableData.value = res.data.rows
          total.value = res.data.total
        } else {
          ElMessage.error(res.msg || '获取操作日志列表失败')
        }
        loading.value = false
      }).catch(() => {
        loading.value = false
        ElMessage.error('获取操作日志列表失败')
      })
    }

    // 查询
    const handleSearch = () => {
      searchForm.pageNum = 1
      getOperLogList()
    }

    // 重置
    const handleReset = () => {
      searchForm.username = ''
      searchForm.operType = ''
      searchForm.module = ''
      searchForm.status = ''
      searchForm.timeRange = []
      handleSearch()
    }

    // 导出
    const handleExport = () => {
      ElMessage.success('日志导出成功')
    }

    // 查看详情
    const handleViewDetail = (row) => {
      currentLog.value = row
      detailVisible.value = true
    }

    // 分页
    const handleSizeChange = (val) => {
      searchForm.pageSize = val
      getOperLogList()
    }

    const handleCurrentChange = (val) => {
      searchForm.pageNum = val
      getOperLogList()
    }

    // 表格选择
    const handleSelectionChange = (selection) => {
      selectedIds.value = selection.map(item => item.id)
    }

    // 删除单条日志
    const handleDelete = (row) => {
      ElMessageBox.confirm('确定要删除该操作日志吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        operLogApi.deleteOperLog(row.id).then(res => {
          if (res.code === 200) {
            ElMessage.success('删除成功')
            getOperLogList()
          } else {
            ElMessage.error(res.msg || '删除失败')
          }
        }).catch(() => {
          ElMessage.error('删除失败')
        })
      }).catch(() => {})
    }

    // 批量删除日志
    const handleDeleteSelected = () => {
      if (selectedIds.value.length === 0) {
        ElMessage.warning('请至少选择一条记录')
        return
      }
      ElMessageBox.confirm(`确定要删除选中的${selectedIds.value.length}条操作日志吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        operLogApi.deleteOperLog(selectedIds.value.join(',')).then(res => {
          if (res.code === 200) {
            ElMessage.success('批量删除成功')
            getOperLogList()
          } else {
            ElMessage.error(res.msg || '批量删除失败')
          }
        }).catch(() => {
          ElMessage.error('批量删除失败')
        })
      }).catch(() => {})
    }

    // 清空日志
    const handleCleanLog = () => {
      ElMessageBox.confirm('确定要清空所有操作日志吗？此操作不可恢复！', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        operLogApi.cleanOperLog().then(res => {
          if (res.code === 200) {
            ElMessage.success('清空操作日志成功')
            getOperLogList()
          } else {
            ElMessage.error(res.msg || '清空操作日志失败')
          }
        }).catch(() => {
          ElMessage.error('清空操作日志失败')
        })
      }).catch(() => {})
    }

    // 组件挂载时获取列表
    onMounted(() => {
      getOperLogList()
    })

    return {
      searchForm,
      dateShortcuts,
      loading,
      currentPage,
      pageSize,
      total,
      tableData,
      selectedIds,
      detailVisible,
      currentLog,
      getOperationTypeTag,
      formatJson,
      handleSearch,
      handleReset,
      handleExport,
      handleViewDetail,
      handleSizeChange,
      handleCurrentChange,
      handleSelectionChange,
      handleDelete,
      handleDeleteSelected,
      handleCleanLog
    }
  }
}
</script>

<style scoped>
.operation-log {
  padding: 20px;
}

.page-header-content {
  font-size: 20px;
  font-weight: bold;
}

.log-content {
  margin-top: 20px;
}

.search-card {
  margin-bottom: 20px;
}

.table-card {
  margin-bottom: 20px;
}

.table-header {
  margin-bottom: 15px;
  display: flex;
  justify-content: space-between;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.code-block {
  margin: 0;
  padding: 8px;
  background-color: #f5f7fa;
  border-radius: 4px;
  font-family: monospace;
  white-space: pre-wrap;
  word-break: break-all;

  &.error {
    color: #f56c6c;
    background-color: #fef0f0;
  }
}

:deep(.el-card__body) {
  padding: 20px;
}
</style> 